#-*- encoding:utf-8 -*-
#用户版图形化界面

#GUI图形库
import tkinter as tk
from tkinter import messagebox

#自定义文件
import RSA_op
import SHA256_op
import File
import Certificate_User
import FTP_op

#初始设置，连接FTP服务器
def startset():
    host = ftp_text.get().lstrip()
    if len(host) == 0:
        messagebox.showwarning('警告','FTP服务器地址不能为空, 请重新输入')
    else:
        try:
            ftp = FTP_op.connect_ftp(host)
            messagebox.showinfo('提示','连接FTP服务器'+host+'成功\n请继续输入用户名')
            btn_setuser['state'] = 'normal'
            btn_setftp.pack_forget()
            ftp_addr['state'] = 'readonly'
            user_input['state'] = 'normal'
        except:
            messagebox.showwarning('警告','连接FTP服务器'+host+'失败')

#绑定用户
def setuser():
    user = user_text.get().lstrip()
    if len(user) == 0:
        messagebox.showwarning('警告','用户名不能为空, 请重新输入')
    else:
        messagebox.showinfo('提示','当前用户'+user+'已绑定, 欢迎您使用本系统')
        btn_setuser.pack_forget()
        user_input['state'] = 'readonly'
        btn_create_file['state'] = 'normal'
        btn_create_key['state'] = 'normal'
        btn_download_file['state'] = 'normal'
        btn_verify['state'] = 'normal'
        find_user_input['state'] = 'normal'
        btn_sign_file['state'] = 'normal'
        btn_verify_file['state'] = 'normal'
        sign_file_input['state'] = 'normal'

#生成密钥文件
def create_key():
    rst = File.create_key_file(user_text.get().lstrip())
    if rst == 1:
        messagebox.showinfo('提示','密钥文件已生成')

#生成证书申请文件
def create_file():
    ftp = FTP_op.connect_ftp(ftp_text.get().lstrip())
    rst = Certificate_User.apply_certificate(ftp, user_text.get().lstrip())
    if rst == -1:
        messagebox.showwarning("警告", "公钥文件不存在，请将公钥文件放在当前目录下")
    else:
        messagebox.showinfo("提示", "证书申请文件已成功生成并上传至FTP")

#下载证书
def download_cer():
    ftp = FTP_op.connect_ftp(ftp_text.get().lstrip())
    rst = Certificate_User.download_certificate(ftp, user_text.get().lstrip())
    if rst == -1:
        messagebox.showinfo("提示", "证书文件尚未签发，下载失败")
    else:
        messagebox.showinfo("提示", "证书已成功下载为"+user_text.get().lstrip()+'_CA.csr')

#验证证书
def verify_cer():
    ftp = FTP_op.connect_ftp(ftp_text.get().lstrip())
    find_user = find_user_text.get().lstrip()
    if len(find_user) == 0:
        messagebox.showwarning('警告','证书持有人姓名不能为空, 请重新输入')
    else:
        rst = Certificate_User.verify_certificate(ftp, find_user)
        if rst == -1:
            messagebox.showwarning('警告','证书文件不存在')
        elif rst == -2:
            messagebox.showwarning('警告','证书文件已被吊销')
        elif rst == -3:
            messagebox.showwarning('警告','证书文件尚未生效')
        elif rst == -4:
            messagebox.showwarning('警告','证书文件已过期')
        elif rst == 0:
            messagebox.showwarning('警告','证书验证不通过，内容可能已被篡改')
        else:
            messagebox.showinfo("提示","该证书通过了验证")

#签名文件
def sign_file():
    if len(sign_file_text.get().lstrip())==0:
        messagebox.showwarning('警告','文件名不能为空, 请重新输入')
    else:
        rst = Certificate_User.sign_file(user_text.get().lstrip(), sign_file_text.get().lstrip()) 
        if rst == -1:
            messagebox.showwarning('警告','原文件或密钥文件不存在')
        else:
            messagebox.showinfo("提示","已生成签名文件"+user_text.get().lstrip()+'_'+sign_file_text.get().lstrip()+'.sign')
        
#验证文件签名
def verify_file():
    if len(sign_file_text.get().lstrip()) == 0:
        messagebox.showwarning('警告','文件名不能为空, 请重新输入')
    elif len(find_user_text.get().lstrip()) == 0:
        messagebox.showwarning('警告','文件持有人姓名不能为空, 请重新输入')
    else:
        var_box = tk.messagebox.askyesno(title='提示',message='当前操作不会验证证书的合法性，请确保证书已通过验证\n是否继续？')
        if var_box:
            rst = Certificate_User.verify_sign_file(find_user_text.get().lstrip(), sign_file_text.get().lstrip())
            if rst == -1:
                messagebox.showwarning('警告','相应文件缺失，请检查文件是否存在')
            elif rst == 0:
                messagebox.showwarning('警告','验证不通过，内容可能已被篡改或文件不属于该用户')
            else:
                messagebox.showinfo("提示","该文件通过了验证")



#说明
def readme():
    messagebox.showinfo('使用说明','\t欢迎使用模拟CA系统的用户端\
    \n注意事项\
    \n1. 使用时需要依次设置CA的FTP服务器地址和当前用户名，一旦设定无法修改，请谨慎操作\
    \n2. 不连接CA的FTP服务器和设置用户名，您将无法正常使用本程序\
    \n3. 密钥文件会生成在本地，与当前程序在同一文件夹下，用户名即为您绑定的用户名，请妥善保管您的密钥，一旦丢失将无法找回\
    \n4. 生成的证书申请文件会保留在当前文件夹下，并会直接传递到CA的FTP服务器中\
    \n5. 下载证书仅能下载当前绑定的用户名的证书，如果远程FTP上没有对应的证书则会下载失败\
    \n6. 验证证书需要将对方的证书放于当前目录下，并需手动在“要验证用户姓名”框中输入证书持有者的用户名\
    \n7. 签名文件需要原文件、公钥、私钥都在当前目录下，生成独立的签名文件\
    \n8. 验证文件签名需要将原文件、签名文件、对方证书放在当前目录下，然后在“要验证用户姓名”框中输入签发文件的用户的姓名\
    \n9. 请勿修改程序生成文件的文件名，防止出现不可预估的后果')

#退出按钮
def cancel():
    root.destroy()

if __name__ == '__main__':
    root = tk.Tk()
    root.title('模拟CA系统-用户版')
    root.geometry("500x250+200+50")  #窗口的大小

    # 第一行（两列）
    row1 = tk.Frame()
    row1.pack(fill="x")
    ftp_text = tk.StringVar()
    tk.Label(row1, text='FTP服务器地址:', width=25).pack(side=tk.LEFT)
    ftp_addr = tk.Entry(row1, textvariable=ftp_text, width=25)
    ftp_addr.pack(side=tk.LEFT)
    btn_setftp = tk.Button(row1, text="①连接", command=startset)
    btn_setftp.pack(side=tk.RIGHT, padx=15)

    # 第二行
    row2 = tk.Frame()
    row2.pack(fill="x", ipadx=1, pady=5)
    user_text = tk.StringVar()
    tk.Label(row2, text='当前用户:', width=25).pack(side=tk.LEFT)
    user_input = tk.Entry(row2, textvariable=user_text, width=25, state=tk.DISABLED)
    user_input.pack(side=tk.LEFT)
    btn_setuser= tk.Button(row2, text="②绑定", command=setuser, state=tk.DISABLED)
    btn_setuser.pack(side=tk.RIGHT, padx=15)

    # 第三行
    row3 = tk.Frame()
    row3.pack(fill="x", ipadx=1, pady=5)
    btn_create_key = tk.Button(row3, text="生成密钥", command=create_key, state=tk.DISABLED)
    btn_create_key.pack(side=tk.LEFT,  padx=40)
    btn_create_file = tk.Button(row3, text="生成证书申请文件", command=create_file, state=tk.DISABLED)
    btn_create_file.pack(side=tk.LEFT,  padx=50)
    btn_download_file = tk.Button(row3, text="下载证书", command=download_cer, state=tk.DISABLED)
    btn_download_file.pack(side=tk.LEFT,  padx=40)

    # 第四行
    row4 = tk.Frame()
    row4.pack(fill="x", ipadx=1, pady=5)
    find_user_text = tk.StringVar()
    tk.Label(row4, text='要验证用户姓名:', width=20).pack(side=tk.LEFT)
    find_user_input = tk.Entry(row4, textvariable=find_user_text, width=25, state=tk.DISABLED)
    find_user_input.pack(side=tk.LEFT)
    btn_verify= tk.Button(row4, text="验证证书", command=verify_cer, state=tk.DISABLED)
    btn_verify.pack(side=tk.RIGHT, padx=35)

    # 第五行
    row5 = tk.Frame()
    row5.pack(fill="x", ipadx=1, pady=5)
    sign_file_text = tk.StringVar()
    tk.Label(row5, text='文件名:', width=20).pack(side=tk.LEFT)
    sign_file_input = tk.Entry(row5, textvariable=sign_file_text, width=25, state=tk.DISABLED)
    sign_file_input.pack(side=tk.LEFT)
    btn_verify_file= tk.Button(row5, text="验证文件", command=verify_file, state=tk.DISABLED)
    btn_verify_file.pack(side=tk.RIGHT, padx=5)
    btn_sign_file= tk.Button(row5, text="签名文件", command=sign_file, state=tk.DISABLED)
    btn_sign_file.pack(side=tk.RIGHT, padx=5)

    # 第六行
    row6 = tk.Frame()
    row6.pack(fill="y", ipadx=10, padx=10, side=tk.BOTTOM)
    tk.Button(row6, text="退出", command=cancel).pack(side=tk.RIGHT)
    tk.Button(row6, text="说明", command=readme).pack(side=tk.RIGHT,  padx=10)

    root.mainloop()